package com.strato.annotation.osgi.v1_0_0.service.handler;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;

import com.strato.base.cache.v1_0_0.TimedReference;

public class DelegateOsgiServiceList implements List<Object> {

	private TimedReference<List<Object>> listRef;
	private WeakReference<BundleContext> bundleContextRef;
	private String query;
	private String interfaceClassName;

	public DelegateOsgiServiceList(Bundle bundle, String query, Class<?> interfaceClass) {
		this.bundleContextRef=new WeakReference<BundleContext>(bundle.getBundleContext());
		this.query=query;
		interfaceClassName=interfaceClass.getName();
	}

	private List<Object> getList(){
		if(listRef!=null&&!listRef.isExpired()){
			List<Object> list = listRef.getObject();
			if(list!=null){
				return list;
			}
		}
		BundleContext bundleContext = bundleContextRef.get();
		List<Object> list=new ArrayList<Object>();
		try {
			ServiceReference<?>[] srs = bundleContext.getServiceReferences(interfaceClassName, query);
			for(ServiceReference<?> sr:srs){
				Object service=bundleContext.getService(sr);
				list.add(service);
			}
		} catch (InvalidSyntaxException e) {
			throw new RuntimeException(e);
		}
		listRef=new TimedReference<List<Object>>(list);
		return list;
	}
	
	@Override
	public boolean add(Object arg0) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void add(int arg0, Object arg1) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean addAll(Collection<? extends Object> arg0) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean addAll(int arg0, Collection<? extends Object> arg1) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void clear() {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean contains(Object arg0) {
		List<Object> list = getList();
		return list.contains(arg0);
	}

	@Override
	public boolean containsAll(Collection<?> arg0) {
		List<Object> list = getList();
		return list.containsAll(arg0);
	}

	@Override
	public Object get(int arg0) {
		List<Object> list = getList();
		return list.get(arg0);
	}

	@Override
	public int indexOf(Object arg0) {
		List<Object> list = getList();
		return list.indexOf(arg0);
	}

	@Override
	public boolean isEmpty() {
		List<Object> list = getList();
		return list.isEmpty();
	}

	@Override
	public Iterator<Object> iterator() {
		List<Object> list = getList();
		return list.iterator();
	}

	@Override
	public int lastIndexOf(Object arg0) {
		List<Object> list = getList();
		return list.lastIndexOf(arg0);
	}

	@Override
	public ListIterator<Object> listIterator() {
		List<Object> list = getList();
		return list.listIterator();
	}

	@Override
	public ListIterator<Object> listIterator(int arg0) {
		List<Object> list = getList();
		return list.listIterator(arg0);
	}

	@Override
	public boolean remove(Object arg0) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Object remove(int arg0) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean removeAll(Collection<?> arg0) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean retainAll(Collection<?> arg0) {
		List<Object> list = getList();
		return list.retainAll(arg0);
	}

	@Override
	public Object set(int arg0, Object arg1) {
		throw new UnsupportedOperationException();
	}

	@Override
	public int size() {
		List<Object> list = getList();
		return list.size();
	}

	@Override
	public List<Object> subList(int arg0, int arg1) {
		List<Object> list = getList();
		return list.subList(arg0, arg1);
	}

	@Override
	public Object[] toArray() {
		List<Object> list = getList();
		return list.toArray();
	}

	@Override
	public <T> T[] toArray(T[] arg0) {
		List<Object> list = getList();
		return list.toArray(arg0);
	}

}
